package com.yupi.yuoj.job.service;

/**
 * @Classname QuestionSyncService
 * @Description 题目同步服务
 * @Date 2025/10/2 15:05
 * @Created by 李胜
 */
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.yupi.yuoj.mapper.QuestionMapper;
import com.yupi.yuoj.model.entity.Question;
import com.yupi.yuoj.model.dto.question.QuestionEsDTO;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import com.yupi.yuoj.repository.QuestionEsRepository;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

@Service
@Slf4j
public class QuestionSyncService {

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private QuestionEsRepository questionEsRepository;

    private final static Gson GSON = new Gson();

    /**
     * 全量同步题目到 ES
     */
    public void syncQuestionsToEs() {
        // 1. 从数据库查询所有题目
        List<Question> questionList = questionMapper.selectList(null);
        if (CollectionUtils.isEmpty(questionList)) {
            return;
        }

        // 2. 转换为 DTO
        List<QuestionEsDTO> questionEsDTOList = questionList.stream()
                .map(this::questionToEsDTO)
                .collect(Collectors.toList());

        // 3. 批量保存到 ES
        final int batchSize = 500;
        int total = questionEsDTOList.size();
        for (QuestionEsDTO questionEsDTO : questionEsDTOList) {
            if (questionEsDTO == null) {
                // 如果 DTO 为 null，说明在转换时就出错了，需要检查 questionToEsDTO 方法
                log.warn("A Question entity could not be converted to DTO.");
                continue;
            }
            try {
                // 逐条保存
                questionEsRepository.save(questionEsDTO);
            } catch (Exception e) {
                // 任何无法被ES接受的“坏数据”都会在这里被捕获
                // 控制台会打印出它的ID，以及导致失败的根本原因
                log.error("！！！发现坏数据！！！同步失败，题目 ID: {}", questionEsDTO.getId(), e);
            }
        }
        log.info("数据同步任务完成。");
    }

    /**
     * 将 Question 实体转换为 QuestionEsDTO
     * @param question
     * @return
     */
    private QuestionEsDTO questionToEsDTO(Question question) {
        QuestionEsDTO questionEsDTO = new QuestionEsDTO();
        questionEsDTO.setId(question.getId());
        questionEsDTO.setTitle(question.getTitle());

        // 直接赋值，不要做任何手动转义或替换！
        // 只要 question.getContent() 是一个普通的 Java String，框架就会处理好一切。
        questionEsDTO.setContent(question.getContent());

        // 对 tags 字段做健壮性处理
        String tagsStr = question.getTags();
        if (tagsStr != null && !tagsStr.isEmpty()) {
            try {
                // 尝试将数据库中的 JSON 字符串解析为 List<String>
                List<String> tagList = GSON.fromJson(tagsStr, new TypeToken<List<String>>() {}.getType());
                questionEsDTO.setTags(tagList);
            } catch (JsonSyntaxException e) {
                // 如果解析失败，说明数据库里的这个 tags 格式有问题
                // 我们可以选择跳过这个字段，或者记录一个错误日志
                log.error("Failed to parse tags for question id: {}. Tags string: {}", question.getId(), tagsStr, e);
                questionEsDTO.setTags(Collections.emptyList()); // 提供一个安全的默认值
            }
        } else {
            questionEsDTO.setTags(Collections.emptyList());
        }

        questionEsDTO.setUserId(question.getUserId());
        questionEsDTO.setCreateTime(question.getCreateTime());
        questionEsDTO.setUpdateTime(question.getUpdateTime());

        return questionEsDTO;
    }
}
